home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Games Extra 1996 September
/
Amiga Games Extra CD-ROM 9-1996.iso
/
userbox
/
publicdomain
/
vim-4.2
/
src
/
gui_athena.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-09
|
27KB
|
1,034 lines
/* vi:set ts=4 sw=4:
*
* VIM - Vi IMproved by Bram Moolenaar
* GUI/Motif support by Robert Webb
* Athena port by Bill Foster
*
* Do ":help uganda" in Vim to read copying and usage conditions.
* Do ":help credits" in Vim to see a list of people who contributed.
*/
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/MenuButton.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/Xaw/Box.h>
#include "vim.h"
#include "globals.h"
#include "proto.h"
#include "option.h"
#include "ops.h"
#include "gui_at_sb.h"
#define puller_width 19
#define puller_height 19
static char puller_bits[] =
{
0x00,0x00,0xf8,0x00,0x00,0xf8,0xf8,0x7f,0xf8,0x04,0x80,0xf8,0x04,0x80,0xf9,
0x84,0x81,0xf9,0x84,0x83,0xf9,0x84,0x87,0xf9,0x84,0x8f,0xf9,0x84,0x8f,0xf9,
0x84,0x87,0xf9,0x84,0x83,0xf9,0x84,0x81,0xf9,0x04,0x80,0xf9,0x04,0x80,0xf9,
0xf8,0xff,0xf9,0xf0,0x7f,0xf8,0x00,0x00,0xf8,0x00,0x00,0xf8
};
extern Widget vimShell;
static Widget vimPanes;
static Widget vimForm = (Widget)NULL;
static Widget textArea;
static Widget scrollbarBox[3]; /* Left, right & bottom scrollbar boxes */
static Widget bottomScrollbar; /* Bottom scrollbar */
static Widget leftBottomScrollFiller; /* Left filler for bottom scrollbar */
static Widget rightBottomScrollFiller; /* Right filler for bottom scrollbar */
static Widget leftScrollbarFiller; /* Filler for left scrollbar */
static Widget rightScrollbarFiller; /* Filler for right scrollbar */
static Widget menuBar;
static void gui_athena_scroll_cb_jump __ARGS((Widget, XtPointer, XtPointer));
static void gui_athena_scroll_cb_scroll __ARGS((Widget, XtPointer, XtPointer));
static void gui_athena_reorder_menus __ARGS((void));
static void gui_athena_pullright_action __ARGS((Widget, XEvent *, String *,
Cardinal *));
static XtActionsRec pullAction = { "menu-pullright",
(XtActionProc)gui_athena_pullright_action };
static XtTranslations parentTrans, menuTrans;
static Pixmap pullerBitmap;
/*
* Scrollbar callback (XtNjumpProc) for when the scrollbar is dragged with the
* left or middle mouse button.
*/
static void
gui_athena_scroll_cb_jump(w, client_data, call_data)
Widget w;
XtPointer client_data, call_data;
{
char_u bytes[4 + sizeof(long_u)];
WIN *wp;
GuiScrollbar *sb;
int sb_num;
int i;
int byte_count;
long_u value;
gui.dragged_sb = SB_NONE;
for (i = 0; i <= SB_BOTTOM; i++)
if (XtParent(w) == scrollbarBox[i])
{
gui.dragged_sb = i;
break;
}
switch (gui.dragged_sb)
{
case SB_LEFT:
case SB_RIGHT:
gui.dragged_wp = (WIN *)client_data;
sb_num = 0;
wp = firstwin;
for ( ; wp != gui.dragged_wp && wp != NULL; wp = wp->w_next)
sb_num++;
if (gui.dragged_wp == NULL)
return;
sb = &wp->w_scrollbar;
value = *((float *)call_data) * (float)sb->max + 0.5;
++value; /* range is 1 to line_count */
sb->value = value;
bytes[0] = CSI;
bytes[1] = KS_SCROLLBAR;
bytes[2] = K_FILLER;
bytes[3] = (char_u)sb_num;
byte_count = 4;
break;
case SB_BOTTOM:
/* why not use sb->max? */
value = *((float *)call_data) *
(float)(gui_get_max_horiz_scroll()) + 0.5;
bytes[0] = CSI;
bytes[1] = KS_HORIZ_SCROLLBAR;
bytes[2] = K_FILLER;
byte_count = 3;
break;
case SB_NONE:
default:
return;
}
add_long_to_buf(value, bytes + byte_count);
add_to_input_buf(bytes, byte_count + sizeof(long_u));
}
/*
* Scrollbar callback (XtNscrollProc) for paging up or down with the left or
* right mouse buttons.
*/
static void
gui_athena_scroll_cb_scroll(w, client_data, call_data)
Widget w;
XtPointer client_data, call_data;
{
char_u bytes[4 + sizeof(long_u)];
WIN *wp;
GuiScrollbar *sb;
int sb_num;
int i;
int byte_count;
long value;
int data = (int)call_data;
for (i = 0; i <= SB_BOTTOM; i++)
if (XtParent(w) == scrollbarBox[i])
{
gui.dragged_sb = i;
break;
}
switch (gui.dragged_sb)
{
case SB_LEFT:
case SB_RIGHT:
gui.dragged_wp = (WIN *)client_data;
sb_num = 0;
wp = firstwin;
for ( ; wp != gui.dragged_wp && wp != NULL; wp = wp->w_next)
sb_num++;
if (gui.dragged_wp == NULL)
return;
sb = &wp->w_scrollbar;
if (sb->size > 5)
i = sb->size - 2; /* use two lines of context */
else
i = sb->size;
switch (data)
{
case ONE_LINE_DATA: data = 1; break;
case -ONE_LINE_DATA: data = -1; break;
case ONE_PAGE_DATA: data = i; break;
case -ONE_PAGE_DATA: data = -i; break;
case END_PAGE_DATA: data = sb->max; break;
case -END_PAGE_DATA: data = -sb->max; break;
default: data = 0; break;
}
value = sb->value + data;
if (value > sb->max)
value = sb->max;
else if (value < 1) /* range is 1 to line_count */
value = 1;
bytes[0] = CSI;
bytes[1] = KS_SCROLLBAR;
bytes[2] = K_FILLER;
bytes[3] = (char_u)sb_num;
byte_count = 4;
break;
case SB_BOTTOM:
if (data < -1)
data = -(Columns - 5);
else if (data > 1)
data = (Columns - 5);
value = curwin->w_leftcol + data;
if (value < 0) /* range is 0 to max_col */
value = 0;
else
{
int max;
/* why not use sb->max here? */
max = gui_get_max_horiz_scroll();
if (value >= max)
value = max;
}
bytes[0] = CSI;
bytes[1] = KS_HORIZ_SCROLLBAR;
bytes[2] = K_FILLER;
byte_count = 3;
break;
case SB_NONE:
default:
return;
}
/*
* This type of scrolling doesn't move the thumb automatically so we need
* make sure the scrollbar still gets updated.
*/
gui.dragged_sb = SB_NONE;
add_long_to_buf((long_u)value, bytes + byte_count);
add_to_input_buf(bytes, byte_count + sizeof(long_u));
}
/*
* Create all the Athena widgets necessary.
*/
void
gui_mch_create_widgets()
{
Dimension base_width, base_height;
/*
* We don't have any borders handled internally by the textArea to worry
* about so only skip over the configured border width.
*/
gui.border_offset = gui.border_width;
base_width = 2 * gui.border_offset;
base_height = 2 * gui.border_offset;
XtInitializeWidgetClass(panedWidgetClass);
XtInitializeWidgetClass(simpleMenuWidgetClass);
XtInitializeWidgetClass(vim_scrollbarWidgetClass);
XtInitializeWidgetClass(labelWidgetClass);
/* Panes for menu bar, middle stuff, and bottom scrollbar box */
vimPanes = XtVaCreateManagedWidget("vimPanes",
panedWidgetClass, vimShell,
XtNorientation, XtorientVertical,
NULL);
/* The top menu bar */
menuBar = XtVaCreateManagedWidget("menuBar",
boxWidgetClass, vimPanes,
XtNmin, gui.menu_height,
XtNborderWidth, 1,
XtNallowResize, True,
XtNresizeToPreferred, True,
XtNskipAdjust, True,
XtNshowGrip, False,
XtNforeground, gui.menu_fg_pixel,
XtNbackground, gui.menu_bg_pixel,
XtNborderColor, gui.menu_fg_pixel,
NULL);
/*
* Panes for the middle stuff (left scrollbar box, text area, and right
* scrollbar box.
*/
vimForm = XtVaCreateManagedWidget("vimForm",
panedWidgetClass, vimPanes,
XtNallowResize, True,
XtNorientation, XtorientHorizontal,
XtNborderWidth, 0,
XtNdefaultDistance, 0,
XtNshowGrip, False,
NULL);
/* Panes for the left window scrollbars. */
scrollbarBox[SB_LEFT] = XtVaCreateWidget("scrollBarBox",
panedWidgetClass, vimForm,
XtNpreferredPaneSize, gui.scrollbar_width,
XtNallowResize, True,
XtNskipAdjust, True,
XtNborderWidth, 1,
XtNshowGrip, False,
XtNforeground, gui.scroll_fg_pixel,
XtNbackground, gui.scroll_fg_pixel,
XtNborderColor, gui.scroll_fg_pixel,
NULL);
/* The text area. */
textArea = XtVaCreateManagedWidget("textArea",
coreWidgetClass, vimForm,
XtNallowResize, True,
XtNshowGrip, False,
XtNbackground, gui.back_pixel,
XtNborderWidth, 0,
XtNheight, Rows * gui.char_height + base_height,
XtNwidth, Columns * gui.char_width + base_width,
NULL);
/* Panes for the right window scrollbars. */
scrollbarBox[SB_RIGHT] = XtVaCreateWidget("scrollBarBox",
panedWidgetClass, vimForm,
XtNpreferredPaneSize, gui.scrollbar_width,
XtNallowResize, True,
XtNskipAdjust, True,
XtNborderWidth, 1,
XtNresizeToPreferred, True,
XtNshowGrip, False,
XtNforeground, gui.scroll_fg_pixel,
XtNbackground, gui.scroll_fg_pixel,
XtNborderColor, gui.scroll_fg_pixel,
NULL);
/* Panes for the bottom scrollbar and fillers on each side. */
scrollbarBox[SB_BOTTOM] = XtVaCreateWidget("scrollBarBox",
panedWidgetClass, vimPanes,
XtNpreferredPaneSize, gui.scrollbar_width,
XtNallowResize, True,
XtNskipAdjust, True,
XtNborderWidth, 1,
XtNresizeToPreferred, True,
XtNshowGrip, False,
XtNforeground, gui.scroll_fg_pixel,
XtNbackground, gui.scroll_fg_pixel,
XtNborderColor, gui.scroll_fg_pixel,
XtNorientation, XtorientHorizontal,
NULL);
/* A filler for the gap on the left side of the bottom scrollbar. */
leftBottomScrollFiller = XtVaCreateManagedWidget("",
labelWidgetClass, scrollbarBox[SB_BOTTOM],
XtNshowGrip, False,
XtNresize, False,
XtNborderWidth, 4,
XtNmin, gui.scrollbar_width + 1,
XtNmax, gui.scrollbar_width + 1,
XtNforeground, gui.scroll_fg_pixel,
XtNbackground, gui.scroll_fg_pixel,
XtNborderColor, gui.scroll_fg_pixel,
NULL);
/* The bottom scrollbar. */
bottomScrollbar = XtVaCreateManagedWidget("bottomScrollBar",
vim_scrollbarWidgetClass, scrollbarBox[SB_BOTTOM],
XtNresizeToPreferred, True,
XtNallowResize, True,
XtNskipAdjust, True,
XtNshowGrip, False,
XtNorientation, XtorientHorizontal,
XtNforeground, gui.scroll_fg_pixel,
XtNbackground, gui.scroll_bg_pixel,
NULL);
XtAddCallback(bottomScrollbar, XtNjumpProc,
gui_athena_scroll_cb_jump, (XtPointer)NULL);
XtAddCallback(bottomScrollbar, XtNscrollProc,
gui_athena_scroll_cb_scroll, (XtPointer)NULL);
vim_XawScrollbarSetThumb(bottomScrollbar, 0., 1., 0.);
/* A filler for the gap on the right side of the bottom scrollbar. */
rightBottomScrollFiller = XtVaCreateManagedWidget("",
labelWidgetClass, scrollbarBox[SB_BOTTOM],
XtNshowGrip, False,
XtNresize, False,
XtNborderWidth, 4,
XtNmin, gui.scrollbar_width + 1,
XtNmax, gui.scrollbar_width + 1,
XtNforeground, gui.scroll_fg_pixel,
XtNbackground, gui.scroll_fg_pixel,
NULL);
/* A filler for the gap on the bottom of the left scrollbar. */
leftScrollbarFiller = XtVaCreateManagedWidget("",
labelWidgetClass, scrollbarBox[SB_LEFT],
XtNshowGrip, False,
XtNresize, False,
XtNborderWidth, 4,
XtNmin, gui.scrollbar_width + 1,
XtNmax, gui.scrollbar_width + 1,
XtNforeground, gui.scroll_fg_pixel,
XtNbackground, gui.scroll_fg_pixel,
NULL);
/* A filler for the gap on the bottom of the right scrollbar. */
rightScrollbarFiller = XtVaCreateManagedWidget("",
labelWidgetClass, scrollbarBox[SB_RIGHT],
XtNshowGrip, False,
XtNresize, False,
XtNborderWidth, 4,
XtNmin, gui.scrollbar_width + 1,
XtNmax, gui.scrollbar_width + 1,
XtNforeground, gui.scroll_fg_pixel,
XtNbackground, gui.scroll_fg_pixel,
NULL);
gui.num_scrollbars = 0;
/*
* Text area callbacks
*/
XtAddEventHandler(textArea, VisibilityChangeMask, FALSE,
gui_x11_visibility_cb, (XtPointer)0);
XtAddEventHandler(textArea, ExposureMask, FALSE, gui_x11_expose_cb,
(XtPointer)0);
XtAddEventHandler(textArea, StructureNotifyMask, FALSE,
gui_x11_resize_window_cb, (XtPointer)0);
XtAddEventHandler(vimShell, FocusChangeMask, FALSE, gui_x11_focus_change_cb,
(XtPointer)0);
XtAddEventHandler(vimPanes, KeyPressMask, FALSE, gui_x11_key_hit_cb,
(XtPointer)0);
XtAddEventHandler(textArea, ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask, FALSE, gui_x11_mouse_cb, (XtPointer)0);
parentTrans = XtParseTranslationTable("<BtnMotion>: highlight() menu-pullright()");
menuTrans = XtParseTranslationTable("<LeaveWindow>: unhighlight() MenuPopdown()\n<BtnUp>: notify() unhighlight() MenuPopdown()\n<BtnMotion>: highlight()");
XtAppAddActions(XtWidgetToApplicationContext(vimForm), &pullAction, 1);
pullerBitmap = XCreateBitmapFromData(gui.dpy, DefaultRootWindow(gui.dpy),
(char *)puller_bits, puller_width, puller_height);
}
int
gui_mch_get_winsize()
{
Dimension base_width, base_height;
Dimension total_width, total_height;
Dimension left_width = 0, right_width = 0;
Dimension bottom_height = 0, menu_height = 0;
base_height = 2 * gui.border_offset;
base_width = 2 * gui.border_offset;
if (gui.which_scrollbars[SB_LEFT])
XtVaGetValues(scrollbarBox[SB_LEFT], XtNwidth, &left_width, NULL);
if (gui.which_scrollbars[SB_RIGHT])
XtVaGetValues(scrollbarBox[SB_RIGHT], XtNwidth, &right_width, NULL);
if (gui.which_scrollbars[SB_BOTTOM])
XtVaGetValues(scrollbarBox[SB_BOTTOM], XtNheight, &bottom_height, NULL);
if (XtIsManaged(menuBar))
XtVaGetValues(menuBar, XtNheight, &menu_height, NULL);
base_width += left_width + right_width;
base_height += menu_height + bottom_height;
XtVaGetValues(vimShell,
XtNheight, &total_height,
XtNwidth, &total_width,
NULL);
gui.num_rows = (total_height - base_height) / gui.char_height;
gui.num_cols = (total_width - base_width) / gui.char_width;
Rows = gui.num_rows;
Columns = gui.num_cols;
gui_reset_scroll_region();
return OK;
}
void
gui_mch_set_winsize()
{
Dimension left_width = 0, right_width = 0;
Dimension bottom_height = 0, menu_height = 0;
Dimension base_width, base_height;
base_width = 2 * gui.border_offset;
base_height = 2 * gui.border_offset;
if (gui.which_scrollbars[SB_LEFT])
XtVaGetValues(scrollbarBox[SB_LEFT], XtNwidth, &left_width, NULL);
if (gui.which_scrollbars[SB_RIGHT])
XtVaGetValues(scrollbarBox[SB_RIGHT], XtNwidth, &right_width, NULL);
if (gui.which_scrollbars[SB_BOTTOM])
XtVaGetValues(scrollbarBox[SB_BOTTOM], XtNheight, &bottom_height, NULL);
if (XtIsManaged(menuBar))
XtVaGetValues(menuBar, XtNheight, &menu_height, NULL);
base_width += left_width + right_width;
base_height += menu_height + bottom_height;
XtVaSetValues(vimShell,
XtNwidthInc, gui.char_width,
XtNheightInc, gui.char_height,
XtNbaseWidth, base_width,
XtNbaseHeight, base_height,
XtNminWidth, base_width + MIN_COLUMNS * gui.char_width,
XtNminHeight, base_height + MIN_ROWS * gui.char_height,
XtNwidth, base_width + Columns * gui.char_width,
XtNheight, base_height + Rows * gui.char_height,
NULL);
}
/*
* Menu stuff.
*/
void
gui_mch_add_menu(menu, parent)
GuiMenu *menu;
GuiMenu *parent;
{
char_u *pullright_name;
if (parent == NULL)
{
menu->id = XtVaCreateManagedWidget(menu->name,
menuButtonWidgetClass, menuBar,
XtNmenuName, menu->name,
XtNforeground, gui.menu_fg_pixel,
XtNbackground, gui.menu_bg_pixel,
NULL);
menu->submenu_id = XtVaCreatePopupShell(menu->name,
simpleMenuWidgetClass, menu->id,
XtNforeground, gui.menu_fg_pixel,
XtNbackground, gui.menu_bg_pixel,
NULL);
gui_athena_reorder_menus();
}
else
{
menu->id = XtVaCreateManagedWidget(menu->name,
smeBSBObjectClass, parent->submenu_id,
XtNforeground, gui.menu_fg_pixel,
XtNbackground, gui.menu_bg_pixel,
XtNrightMargin, puller_width,
XtNrightBitmap, pullerBitmap,
NULL);
XtAddCallback(menu->id, XtNcallback, gui_x11_menu_cb,
(XtPointer)menu);
pullright_name = strnsave(menu->name, strlen(menu->name) +
strlen("-pullright"));
strcat(pullright_name, "-pullright");
menu->submenu_id = XtVaCreatePopupShell(pullright_name,
simpleMenuWidgetClass, parent->submenu_id,
XtNforeground, gui.menu_fg_pixel,
XtNbackground, gui.menu_bg_pixel,
XtNtranslations, menuTrans,
NULL);
vim_free(pullright_name);
XtOverrideTranslations(parent->submenu_id, parentTrans);
}
}
void
gui_mch_add_menu_item(menu, parent)
GuiMenu *menu;
GuiMenu *parent;
{
menu->submenu_id = (Widget)0;
menu->id = XtVaCreateManagedWidget(menu->name,
smeBSBObjectClass, parent->submenu_id,
XtNforeground, gui.menu_fg_pixel,
XtNbackground, gui.menu_bg_pixel,
NULL);
XtAddCallback(menu->id, XtNcallback, gui_x11_menu_cb,
(XtPointer)menu);
}
/*
* Destroy the machine specific menu widget.
*/
void
gui_mch_destroy_menu(menu)
GuiMenu *menu;
{
if (menu->id != (Widget)NULL)
{
/*
* This is a hack for the Athena simpleMenuWidget to keep it from
* getting a BadValue error when it's last child is destroyed. We
* check to see if this is the last child and if so, go ahead and
* delete the parent ahead of time. The parent will delete it's
* children like all good widgets do.
*/
if (XtParent(menu->id) != menuBar)
{
int num_children;
XtVaGetValues(XtParent(menu->id),
XtNnumChildren, &num_children, NULL);
if (num_children <= 1)
XtDestroyWidget(XtParent(menu->id));
else
XtDestroyWidget(menu->id);
}
else
XtDestroyWidget(menu->id);
menu->id = (Widget)NULL;
}
}
/*
* Reorder the menus so "Help" is the rightmost item on the menu.
*/
static void
gui_athena_reorder_menus()
{
Widget *children;
Widget help_widget = (Widget)NULL;
int num_children;
int i;
XtVaGetValues(menuBar,
XtNchildren, &children,
XtNnumChildren, &num_children,
NULL);
XtUnmanageChildren(children, num_children);
for (i = 0; i < num_children - 1; i++)
if (help_widget == (Widget)NULL)
{
if (strcmp((char *)XtName(children[i]), "Help") == 0)
{
help_widget = children[i];
children[i] = children[i + 1];
}
}
else
children[i] = children[i + 1];
if (help_widget != (Widget)NULL)
children[num_children - 1] = help_widget;
XtManageChildren(children, num_children);
}
/*
* Scrollbar stuff:
*/
void
gui_mch_create_which_components()
{
static int prev_which_scrollbars[3] = {-1, -1, -1};
static int prev_menu_is_active = -1;
int i;
WIN *wp;
/*
* When removing the left/right scrollbar and creating the right/left
* scrollbar, we have to force a redraw (the size of the text area doesn't
* change).
*/
if (prev_which_scrollbars[SB_LEFT] != gui.which_scrollbars[SB_LEFT] &&
prev_which_scrollbars[SB_RIGHT] != gui.which_scrollbars[SB_RIGHT])
must_redraw = CLEAR;
gui_x11_use_resize_callback(textArea, FALSE);
for (i = 0; i < 3; i++)
{
if (gui.which_scrollbars[i] != prev_which_scrollbars[i])
{
if (gui.which_scrollbars[i])
{
switch (i)
{
/* When adding the left one, we need to reorder them all */
case SB_LEFT:
XtUnmanageChild(textArea);
if (gui.which_scrollbars[SB_RIGHT])
XtUnmanageChild(scrollbarBox[SB_RIGHT]);
XtManageChild(scrollbarBox[SB_LEFT]);
XtManageChild(textArea);
if (gui.which_scrollbars[SB_RIGHT])
XtManageChild(scrollbarBox[SB_RIGHT]);
/*
* When adding at the left and we have a bottom
* scrollbar, we need to reorder these too.
*/
if (gui.which_scrollbars[SB_BOTTOM])
{
XtUnmanageChild(bottomScrollbar);
if (gui.which_scrollbars[SB_RIGHT])
XtUnmanageChild(rightBottomScrollFiller);
XtManageChild(leftBottomScrollFiller);
XtManageChild(bottomScrollbar);
if (gui.which_scrollbars[SB_RIGHT])
XtManageChild(rightBottomScrollFiller);
}
break;
case SB_RIGHT:
XtManageChild(rightBottomScrollFiller);
XtManageChild(scrollbarBox[i]);
break;
case SB_BOTTOM:
/* Unmanage the bottom scrollbar and fillers */
XtUnmanageChild(leftBottomScrollFiller);
XtUnmanageChild(bottomScrollbar);
XtUnmanageChild(rightBottomScrollFiller);
/*
* Now manage the bottom scrollbar and fillers that
* are supposed to be there.
*/
if (gui.which_scrollbars[SB_LEFT])
XtManageChild(leftBottomScrollFiller);
XtManageChild(bottomScrollbar);
if (gui.which_scrollbars[SB_RIGHT])
XtManageChild(rightBottomScrollFiller);
XtManageChild(scrollbarBox[i]);
break;
}
}
else
{
switch (i)
{
case SB_LEFT:
XtUnmanageChild(leftBottomScrollFiller);
break;
case SB_RIGHT:
XtUnmanageChild(rightBottomScrollFiller);
break;
}
XtUnmanageChild(scrollbarBox[i]);
}
}
if (gui.which_scrollbars[i] != prev_which_scrollbars[i])
{
if (i == SB_LEFT || i == SB_RIGHT)
{
if (gui.which_scrollbars[i])
{
/* Scrollbar box has just appeared */
gui.new_sb[i] = TRUE;
}
else if (prev_which_scrollbars[i] == TRUE)
{
/* Scrollbar box has just been deleted */
for (wp = firstwin; wp != NULL; wp = wp->w_next)
XtDestroyWidget(wp->w_scrollbar.id[i]);
}
}
}
prev_which_scrollbars[i] = gui.which_scrollbars[i];
}
if (gui.menu_is_active != prev_menu_is_active)
{
if (gui.menu_is_active)
{
XtUnmanageChild(menuBar);
XtUnmanageChild(vimForm);
if (gui.which_scrollbars[SB_BOTTOM])
XtUnmanageChild(scrollbarBox[SB_BOTTOM]);
XtManageChild(menuBar);
XtManageChild(vimForm);
if (gui.which_scrollbars[SB_BOTTOM])
XtManageChild(scrollbarBox[SB_BOTTOM]);
}
else
XtUnmanageChild(menuBar);
prev_menu_is_active = gui.menu_is_active;
}
gui_x11_use_resize_callback(textArea, TRUE);
if (vimForm != (Widget)NULL && XtIsRealized(vimForm))
gui_mch_set_winsize();
}
/*
* Vertical scrollbar stuff:
*/
void
gui_mch_update_scrollbars(worst_update, which_sb)
int worst_update;
int which_sb; /* SB_LEFT or SB_RIGHT */
{
WIN *wp;
GuiScrollbar *sb;
int idx;
Dimension h; /* Height of scrollbar (in pixels) */
Dimension y; /* Coord of top of scrollbar (in pixels) */
int tmp;
float val = 0., size = 0.;
if (worst_update >= SB_UPDATE_HEIGHT)
{
XawPanedSetRefigureMode(scrollbarBox[which_sb], False);
gui_x11_use_resize_callback(textArea, FALSE);
}
/*
* This has to get cleared manually since Athena doesn't tell us when the
* draggin' stops.
*/
gui.dragged_sb = SB_NONE;
for (wp = firstwin, idx = 0; wp; wp = wp->w_next, idx++)
{
sb = &wp->w_scrollbar;
if (sb->update[which_sb] >= SB_UPDATE_VALUE)
{
val = (float)(sb->value - 1) / (float)sb->max;
size = (float)sb->size / (float)sb->max;
}
if (sb->update[which_sb] == SB_UPDATE_CREATE)
{
sb->id[which_sb] = XtVaCreateManagedWidget("scrollBar",
vim_scrollbarWidgetClass, scrollbarBox[which_sb],
XtNborderWidth, 1,
XtNdefaultDistance, 0,
XtNallowResize, True,
XtNpreferredPaneSize, True,
XtNresizeToPreferred, True,
XtNskipAdjust, True,
XtNorientation, XtorientVertical,
XtNshowGrip, False,
XtNforeground, gui.scroll_fg_pixel,
XtNbackground, gui.scroll_bg_pixel,
NULL);
XtAddCallback(sb->id[which_sb], XtNjumpProc,
gui_athena_scroll_cb_jump, (XtPointer)wp);
XtAddCallback(sb->id[which_sb], XtNscrollProc,
gui_athena_scroll_cb_scroll, (XtPointer)wp);
}
if (sb->update[which_sb] >= SB_UPDATE_HEIGHT)
{
h = sb->height * gui.char_height
+ sb->status_height * gui.char_height / 2;
y = wp->w_winpos * gui.char_height + gui.border_offset;
if (wp == firstwin)
{
/* Height of top scrollbar includes width of top border */
h += gui.border_offset;
}
else
{
/*
* Height of other scrollbars includes half of status bar above
*/
tmp = wp->w_prev->w_status_height * (gui.char_height + 1) / 2;
h += tmp;
y -= tmp;
}
XtVaSetValues(sb->id[which_sb],
XtNheight, h,
XtNmin, h,
XtNmax, h,
XtNy, y,
NULL);
vim_XawScrollbarSetThumb(sb->id[which_sb], val, size, 1.0);
}
else if (sb->update[which_sb] == SB_UPDATE_VALUE)
{
vim_XawScrollbarSetThumb(sb->id[which_sb], val, size, 1.0);
}
sb->update[which_sb] = SB_UPDATE_NOTHING;
}
if (worst_update >= SB_UPDATE_HEIGHT)
{
if (worst_update >= SB_UPDATE_CREATE)
gui_mch_reorder_scrollbars(which_sb);
XawPanedSetRefigureMode(scrollbarBox[which_sb], True);
gui_x11_use_resize_callback(textArea, TRUE);
}
}
void
gui_mch_reorder_scrollbars(which_sb)
int which_sb;
{
WIN *wp;
if (which_sb == SB_LEFT)
XtUnmanageChild(leftScrollbarFiller);
else
XtUnmanageChild(rightScrollbarFiller);
for (wp = firstwin; wp != NULL; wp = wp->w_next)
if (wp->w_scrollbar.id[which_sb] != NULL)
XtUnmanageChild(wp->w_scrollbar.id[which_sb]);
for (wp = firstwin; wp != NULL; wp = wp->w_next)
if (wp->w_scrollbar.id[which_sb] != NULL)
XtManageChild(wp->w_scrollbar.id[which_sb]);
if (which_sb == SB_LEFT)
XtManageChild(leftScrollbarFiller);
else
XtManageChild(rightScrollbarFiller);
}
void
gui_mch_destroy_scrollbar(wp)
WIN *wp;
{
if (gui.which_scrollbars[SB_LEFT])
XtDestroyWidget(wp->w_scrollbar.id[SB_LEFT]);
if (gui.which_scrollbars[SB_RIGHT])
XtDestroyWidget(wp->w_scrollbar.id[SB_RIGHT]);
gui.num_scrollbars--;
}
/*
* Horizontal scrollbar stuff:
*/
void
gui_mch_update_horiz_scrollbar(value, size, max)
int value;
int size;
int max;
{
static int prev_value = -1, prev_size = -1, prev_max = -1;
float val, shown, maxval;
if (value == prev_value && size == prev_size && max == prev_max)
return;
prev_value = value;
prev_size = size;
prev_max = max;
if (max == 1) /* maximum is one more than maximal value */
{
val = 0.0;
shown = 1.0;
maxval = 0.0;
}
else
{
val = (float)value / (float)max;
shown = (float)size / (float)max;
maxval = 1.0;
}
vim_XawScrollbarSetThumb(bottomScrollbar, val, shown, maxval);
}
Window
gui_mch_get_wid()
{
return( XtWindow(textArea) );
}
static void
gui_athena_pullright_action(w, event, args, nargs)
Widget w;
XEvent *event;
String *args;
Cardinal *nargs;
{
Widget menuw;
Dimension width, height;
char_u *pullright_name;
Widget popup;
if (event->type != MotionNotify)
return;
/* Get the active entry for the current menu */
if ((menuw = XawSimpleMenuGetActiveEntry(w)) == (Widget)NULL)
return;
XtVaGetValues(w,
XtNwidth, &width,
XtNheight, &height,
NULL);
if (event->xmotion.x >= width || event->xmotion.y >= height)
return;
/* We do the pull-off when the pointer is in the rightmost 1/4th */
if (event->xmotion.x < (width * 3) / 4)
return;
pullright_name = strnsave(XtName(menuw), strlen(XtName(menuw)) +
strlen("-pullright"));
strcat(pullright_name, "-pullright");
popup = XtNameToWidget(w, pullright_name);
vim_free(pullright_name);
if (popup == (Widget)NULL)
return;
XtVaSetValues(popup,
XtNx, event->xmotion.x_root,
XtNy, event->xmotion.y_root - 7,
NULL);
XtPopup(popup, XtGrabExclusive);
}